/* vehicleState wrappa il Path di un veicolo con le informazioni associate al suo stato. */
#ifndef VEHICLESTATE_H_
#define VEHICLESTATE_H_

#include "vehiclePath.h"
#include "edgeGraph.h"

typedef unsigned int Natural;

typedef struct VehicleState {

	/* Percorso effettuato dal veicolo, in termini di attraversamenti ed eventuali servizi.
	 * Attenzione, è un puntatore poichè rappresenta la testa di una lista! */
	PvehiclePath pvp;
	/** Quantità di tempo utilizzata dal veicolo. Per costruzione assume valori in [0,Tmax].
	 *  E' utilizzata principalmente come cache per non ricomputare un numero smisurato di volte.*/
	int tau;
	/** Quantità di servizi offerti dal veicolo. Per costruzione assume valori in [0,Q].
	 *  E' utilizzata principalmente come cache per non ricomputare un numero smisurato di volte.*/
	int theta;
	/** Quantità di profitto ottenuto dal veicolo. Per costruzione assume valori in [0,Inf).
	 *  E' utilizzata principalmente come cache per non ricomputare un numero smisurato di volte.*/
	int jk;
	/** Numero di archi attraversati coinvolti nel percorso. Per esempio se il percorso e' semplicemente
	 * un arco doppio questo campo varra' 2.
	 */
	int lEdges;
	/** Numero di nodi coinvolti nel percorso. */
	int lNodes;
	/**lunghezza della  lista contenuta in vp (sentinella esclusa). Per esempio se il percorso e'
	 * semplicemente un arco doppio questo campo varra' 1.*/
	int pathSize;

} VehicleState;

typedef VehicleState* PvehicleState;

/** Inizializza uno stato vergine, con un percorso nullo e dei campi cache pari a zero. */
PvehicleState initVehicleState();

/**dealloca dalla memoria lo state
 *
 * \pre
 *  \li state non e' NULL
 * \post
 *  \li viene deallocata la memoria occupata da VehiclePath nonche' dagli altri campi
 *  di VehicleState.
 *
 * @param state lo stato da deallocare
 */
void freeVehicleState(PvehicleState state);

/** Aggiunge un nuovo arco percorso da un camion all'interno dello stato passato come parametro.
 *
 *  \pre
 *   \li edge non NULL
 *   \li edge ha i<j
 *   \li pvs non NULL
 *   \li se g_ok=TRUE l'arco non deve essere ancora stato soddisfatto
 *	\post
 *	 \li l'arco e' all'interno del percorso del camion
 *	 \li il campo tau viene incrementato della quantita' e->t
 *	 \li il campo theta viene incrementato della quantita' e->d, se possibile
 *	 \li il campo jk viene incrementato della quantita' e->p, se possibile
 *	 \li la matrice G è aggiornata, se possibile
 *
 *	se possibile si riferisce alla situazione di G. difatti i controlli TQ sono altrove!!
 *
 * @param id identifica l'arco da aggiungere in lista
 * @param path indica la lista che deve essere aggiornata
 * @param e descrive l'arco da aggiungere alla lista. Contiene:
 * 		  \li t il tempo che viene consumato per attraversare l'arco 'id'
 *        \li d la capacita' che può esser consumata per l'arco 'id'
 *        \li p il profitto che può esser raccolto dall'arco 'id'
 * @param k l'identificativo del veicolo sul cui stato si sta operando. Necessario per un aggiornamento di GMatrix
 * @param g_ok indica se l'arco deve essere soddisfatto oppure no
 */
void addEdgeToVehicleState(PedgeID pid, PedgeGraph pe, PvehicleState pvs, bool g_ok);

/** Metodo da richiamare per modificare uno state prima di testarne la connettività.
 *  Opera ristrettamente sui campi di VehicleState, in particolare modifica solamente vehiclePath e lEdges.
 *  <b>Non deve essere quindi utilizzato</b> per aggiungere archi nella normale soluzione poiche' non vengono aggiornati
 *  altri valori fondamentali (come la gMatrix per esempio).
 *
 *  \pre
 *   \li pid non NULL
 *   \li pid validato correttamente
 *   \li pvs non NULL
 *  \post
 *   \li all'interno della struttura pvp di pvs e' comparsa una percorrenza dell'arco pid in piu' rispetto a prima di questa chiamata
 *
 * @param pid l'arco da aggiungere
 * @param pvs il percorso del camion da aggiungere
 */
void addEdgeToVehicleStateForConnectionTest(PedgeID pid, PvehicleState pvs);

/** Metodo da richiamare per modificare uno state prima di testarne la connettività.
 *  Opera ristrettamente sui campi di VehicleState ed in particolare modifica solamente vehiclePath e lEdges.
 *  La funzione <b>non deve essere quindi utilizzata</b> per togliere archi dalla normale soluzione poiche' non vengono aggiornati
 *  altri valori fondamentali (come la gMatrix per esempio).
 *
 * \pre
 *  \li pid indica un edgeID che è presente nel path associato allo state.
 *  \li pid validato
 *  \li pvs non NULL
 *
 * \post
 *  \li all'interno del campo pvp di pvs l'arco pid viene percorso una volta in meno rispetto a prima di questa chiamata a funzione
 *
 * @param pid l'arco da togliere
 * @param pvs il percorso del camion da modificare
 */
void removeEdgeFromVehicleStateForConnectionTest(PedgeID pid, PvehicleState pvs);

/**rimuove UNA percorrenza dell'arco specificato dallo stato del camion.
  *
 *  \pre
 *   \li edge non NULL
 *   \li edge ha i<j
 *   \li pvs non NULL
 *	\post
 *	 \li l'arco e' all'interno del percorso del camion
 *	 \li il campo tau viene decrementato della quantita' e->t
 *	 \li il campo theta viene decrementato della quantita' e->d, se possibile
 *	 \li il campo jk viene decrementato della quantita' e->p, se possibile
 *	 \li la matrice G è aggiornata, se possibile
 *
 *	se possibile si riferisce alla situazione di G.
 *
 * @param id identifica l'arco da rimuovere in lista
 * @param path indica la lista che deve essere aggiornata
 * @param e descrive l'arco da rimuovere dalla lista. Contiene:
 * 		  \li t il tempo che viene consumato per attraversare l'arco 'id'
 *        \li d la capacita' che può esser consumata per l'arco 'id'
 *        \li p il profitto che può esser raccolto dall'arco 'id'
 * @param g_ok TRUE se il camion raccoglieva il nodo, FALSE altrimenti
 * @return il numero di volte che l'arco edge viene percorso dopo aver eseguito questa funzione
 * */
int removeEdgeFromVehicleState(PedgeID pid, PedgeGraph pe, PvehicleState pvs, bool g_ok);

/**genera una nuova istanza di VehicleState uguale a quella passata come parametro. I campi vengono copiati
 * in conformita' a questa tabella:
 *
 * <table>
 * 	<tr>
 * 	 <th>Campo</th>
 * 	 <th>copia per...</th>
 * 	</tr>
 * 	<tr>
 * 	 <td>pvp</td>
 * 	 <td>fisica</td>
 * 	</tr>
 * 	<tr>
 * 	 <td>tau</td>
 * 	 <td>fisica</td>
 * 	</tr>
 * 	<tr>
 * 	 <td>theta</td>
 * 	 <td>fisica</td>
 * 	</tr>
 * 	<tr>
 * 	 <td>jk</td>
 * 	 <td>fisica</td>
 * 	</tr>
 * 	<tr>
 * 	 <td>lEdges</td>
 * 	 <td>fisica</td>
 * 	</tr>
 * 	<tr>
 * 	 <td>lNodes</td>
 * 	 <td>fisica</td>
 * 	</tr>
 * 	<tr>
 * 	 <td>pathSize</td>
 * 	 <td>fisica</td>
 * 	</tr>
 * </table>
 *
 * \pre
 *  \li pstate non NULL
 * \post
 *  \li una istanza di VehicleState viene allocata in memoria. La sua deallocazione deve essere <b>manuale</b>
 *
 * @param state lo stato da copiare
 * @return un puntatore ad un'istanza di vehicleState in memoria uguale a tutto per tutto all'originale
 */
PvehicleState cloneVehicleState(PvehicleState pstate);

/**determina se il percorso passato e' connesso oppure e' disconnesso.
 *
 * \pre
 *  \li path non e' NULL
 *  \li
 *
 * @param il path da controllare
 * @param la lunghezza del path in numero di archi attraversati.
 * @return TRUE se il percorso e' connesso, FALSE altrimenti
 */
bool isConnected(PvehiclePath p_path, int lEdges);

/* \pre
 * \li i marked devono essere gia' stati inizializzati
 *
 *@return il numero di archi attraversati (gli archi doppi ocntano 2)
 */
int isConnectedRecursive(int node, PvehiclePath p_path);

/** Richiama printVehiclePath e vi appende i valori di tau e di theta.
 *
 * \pre
 *  \li f aperto in scrittura
 *  \li pvs non NULL
 * \post
 *  \li f modificato
 *
 * @param f il file su cui stampare
 * @param pvs il percorso del camion da stamapre
 * @param k il numero del camion che compie il percorso
 */
void printVehicleState(FILE* f, PvehicleState pvs, int k);

void printVehicleTQJScalars(FILE* f, PvehicleState pvs);
void printVehicleAllScalars(FILE* f, PvehicleState pvs);

#endif /* VEHICLESTATE_H_ */
